#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<queue>
#include<vector>
#include<Windows.h>
#include<stdlib.h>
#include<thread>
#include<mutex>
#include<functional>
#include<atomic>
#include<time.h>
using namespace std;


//递归终止函数
template <class T>
void ShowList(const T& t)
{
	cout << t << ":end" << endl;
}

// 可变模板参数
template<class T , class ...Args>
void ShowList(T val,Args... args)
{
	cout << typeid(val).name() << ":"<< val << endl;
	ShowList(args...);
}

// 线程函数
void Print(int n)
{
	for (int i = 0; i < n; i++)
	{
		cout << i << " ";
	}
	cout << endl;
}

int Max(int a, int b, int c)
{
	int max = a;
	if (b > max)
		max = b;
	if (c > max)
		max = c;
	return max;
}

void test1()
{
	function<int(int, int)> f = bind(Max, 3, placeholders::_1, placeholders::_2);
	cout << f(1, 5);
}

// 两线程对同一变量++
//atomic<int> x = 0;
mutex mtx;


//void test2()
//{
//	thread t1(func, 10000000);
//	thread t2(func, 20000000);
//	t1.join();
//	t2.join();
//
//}

void func(int& pn)
{
	pn += 10;
}

// 锁的守卫，如果在拿着锁期间进程异常退出作用域，会自动调用析构函数释放锁
// 避免了死锁情况
template<class Lock>
class LockGuard
{
public:
	LockGuard(Lock& lock)
		:_lock(lock)
	{
		_lock.lock();
	}
	~LockGuard()
	{
		_lock.unlock();
	}
private:
	Lock& _lock;// 锁不能赋值，所以这里使用引用
};


void routine(vector<int>& v,int n,int base)
{
	
	for (int i = 0; i < n; ++i)
	{
		LockGuard<mutex> lock(mtx);
		v.push_back(base + i);
	}
}



void test3()
{
	int a = 0;
	thread t1(func, ref(a));
	t1.join();
	cout << a << endl;
	cout << a << endl;
	cout << a << endl;
	cout << a << endl;
	cout << a << endl;
	cout << a << endl;
	cout << a << endl;
	cout << a << endl;

}

void test4()
{
	vector<int> v;
	thread t1(routine, ref(v), 100, 1000); // 引用参数需要用ref函数修饰之后再传，否则运行出错
	thread t2(routine, ref(v), 100, 2000);
	t1.join();
	t2.join();
	for (auto& e : v)
	{
		cout << e << " ";
	}
}


// 使用条件变量实现两个线程交替打印奇偶数
void test5()
{
	int i = 0;
	int n = 100;
	mutex mtx1;
	condition_variable cv;
	bool flag = false;
	thread t1([&i,&n,&cv,&mtx1,&flag]()->
		void{
			while (i < n)
			{
				unique_lock<mutex> lock(mtx1);
				cv.wait(lock, [&flag]()-> bool{return !flag; });
				cout << this_thread::get_id() << "(偶数):" << i << endl;
				++i;
				flag = true;
				// 唤醒另一个等待线程；
				cv.notify_one();
			}
		}
	);
	thread t2([&i, &n, &cv, &mtx1, &flag]()
		{
			while (i < n)
			{
				unique_lock<mutex> lock(mtx1);
				// cv.wait(lock, [&flag]()-> bool {return flag; });
				while (!flag)
				{
					cv.wait(lock);
				}
				cout << this_thread::get_id() << "(奇数):" << i << endl;
				++i;
				flag = false;
				cv.notify_one();
			}
		}
	);
	// 等待线程退出，清理资源
	t1.join();
	t2.join();

}

void test6()
{

}

int main()
{
	//test2();
	//test3();
	//test4();
	test5();
	return 0;
}